<template>
  <SelectTrigger label="点特效" :options="options" width="350px" />
  <div id="cesiumContainer"></div>
</template>
<script setup>

import * as Cesium from "cesium";
import TOKEN from "@/utils/cesium/token.js";

const options = ref([]);
/**
 * 自定义材质特效
 */
onMounted(() => {
  Cesium.Ion.defaultAccessToken = TOKEN;
  // 实例化
  const viewer = new Cesium.Viewer("cesiumContainer");


  // 声明一个初始材质
  const defaultMaterial = new Cesium.Material.fromType('Color')
  defaultMaterial.uniforms.color = Cesium.Color.RED
  const defaultAppreance = new Cesium.MaterialAppearance({
    material: defaultMaterial
  })

  // 多边形
  const polygonPrimitive = new Cesium.Primitive({
    geometryInstances: new Cesium.GeometryInstance({
      geometry: new Cesium.PolygonGeometry({
        polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray([
          114, 25,
          114.01, 25,
          114.01, 25.01,
          114, 25.01,
        ])),
        height: 1000
      })
    }),
    appearance: defaultAppreance
  })
  // 正方体
  const boxPrimitive = new Cesium.Primitive({
    geometryInstances: new Cesium.GeometryInstance({
      geometry: Cesium.BoxGeometry.fromDimensions({
        dimensions: new Cesium.Cartesian3(1000, 1000, 1000)
      }),
      modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(114.005, 25.02, 1000))
    }),
    appearance: defaultAppreance
  })
  // 直线
  const polylinePrimitive = new Cesium.Primitive({
    geometryInstances: new Cesium.GeometryInstance({
      geometry: new Cesium.PolylineGeometry({
        positions: Cesium.Cartesian3.fromDegreesArrayHeights([
          114.02, 25.02, 1000,
          114.05, 25.02, 1000
        ]),
        width: 2,
      })
    }),
    appearance: new Cesium.PolylineMaterialAppearance({
      material: defaultMaterial
    })
  })
  // 球体
  const ellipsoidPrimitive = new Cesium.Primitive({
    geometryInstances: new Cesium.GeometryInstance({
      geometry: new Cesium.EllipsoidGeometry({
        radii: new Cesium.Cartesian3(1000, 1000, 1000),
      }),
      modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(114.03, 25.005, 1000))
    }),
    appearance: defaultAppreance
  })

  viewer.scene.primitives.add(polygonPrimitive)
  viewer.scene.primitives.add(boxPrimitive)
  viewer.scene.primitives.add(polylinePrimitive)
  viewer.scene.primitives.add(ellipsoidPrimitive)

  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(114.02, 25.01, 10000),
    duration: 0
  })


  options.value = [
    {
      text: "自定义材质（相当于纯色材质）",
      onselect: function () {
        // 片元着色器
        const shaderSource = `
          // 接受 uniform 传参 为四维向量 color 代表颜色
          uniform vec4 color;
          
          // 需要返回 czm_material 类型结构体 , 逐顶点绘制
          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            // 定义颜色变量 , 因为 color 为uniform 类型，无法修改
            vec4 outColor = color;
            // 获取默认的一个结构体，在此结构体上进行修改
            czm_material material = czm_getDefaultMaterial(materialInput);
            // material.diffuse : vec3 类型的漫反射光
            material.diffuse = czm_gammaCorrect(outColor.rgb);  // czm_gammaCorrect 伽马效正，在不同设备上显示相同的效果
            material.alpha = outColor.a; // 透明度
            return material;
          }
        `
        const myMaterial = new Cesium.Material({
          translucent: false, // 透明效果
          fabric: {
            type: 'test',
            uniforms: {
              color: new Cesium.Color(0, 1, 0, 1),
            },
            source: shaderSource
          }
        })
        setMeterial(myMaterial) // 设置材质
      }
    },
    {
      text: "自定义材质-渐变色（静态）",
      onselect: function () {
        // 片元着色器
        const shaderSource = `
          // 接受 uniform 传参 为四维向量 color 代表颜色
          uniform vec4 color;
          
          // 需要返回 czm_material 类型结构体 , 逐顶点绘制
          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            // 定义颜色变量 , 因为 color 为uniform 类型，无法修改
            vec4 outColor = color;
            // 获取默认的一个结构体，在此结构体上进行修改
            czm_material material = czm_getDefaultMaterial(materialInput);
            // material.diffuse : vec3 类型的漫反射光

            // materialInput.st UV 坐标（已插值） 范围在【0,1】  st.s 为水平分量  st.t 为垂直分量
            vec2 st = materialInput.st;

            // fract 是返回小数部分
            float groupNumb = 3.0;// 分组的数量
            outColor.a = fract(st.s * groupNumb) ; // 改变透明分量
            outColor.r = fract(st.s * groupNumb); // 分成3段渐变

            material.diffuse = czm_gammaCorrect(outColor.rgb);  // czm_gammaCorrect 伽马效正，在不同设备上显示相同的效果
            material.alpha = outColor.a; // 透明度
            return material;
          }
        `
        const myMaterial = new Cesium.Material({
          translucent: false,
          fabric: {
            type: 'test',
            uniforms: {
              color: new Cesium.Color(1, 0, 0, 1),
            },
            source: shaderSource
          }
        })
        setMeterial(myMaterial) // 设置材质
      }
    },
    {
      text: "自定义材质-动态线(x方向)",
      onselect: function () {
        // 片元着色器
        const shaderSource = `
          // 接受 uniform 传参 为四维向量 color 代表颜色
          uniform vec4 color;
          uniform float lineWidth;
          uniform float speed;
          
          // 需要返回 czm_material 类型结构体 , 逐顶点绘制
          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            // 定义颜色变量 , 因为 color 为uniform 类型，无法修改
            vec4 outColor = color;
            // 获取默认的一个结构体，在此结构体上进行修改
            czm_material material = czm_getDefaultMaterial(materialInput);

            // materialInput.st UV 坐标（已插值） 范围在【0,1】  st.s 为水平分量  st.t 为垂直分量
            vec2 st = materialInput.st;

            float time = fract(czm_frameNumber * speed / 600.0); // czm_frameNumber 为自增变量,除以60帧,为一次动画的计数器
            float xPosition = time; // 设置 线的位置为 时间的位置

            if(st.s > xPosition - lineWidth/2.0 && st.s < xPosition + lineWidth/2.0) {
              outColor = vec4(0,0,1,1);
            }

            material.diffuse = czm_gammaCorrect(outColor.rgb);  // czm_gammaCorrect 伽马效正，在不同设备上显示相同的效果
            material.alpha = outColor.a; // 透明度
            return material;
          }
        `
        const myMaterial = new Cesium.Material({
          translucent: false,
          fabric: {
            type: 'test',
            uniforms: {
              color: new Cesium.Color(1, 0, 0, 1),
              lineWidth: 0.1, // 线的宽度， 0-1 之间 为占比
              speed: 10, // 速度
            },
            source: shaderSource
          }
        })
        setMeterial(myMaterial) // 设置材质
      }
    },
    {
      text: "自定义材质-动态线(y方向)",
      onselect: function () {
        // 片元着色器
        const shaderSource = `
          // 接受 uniform 传参 为四维向量 color 代表颜色
          uniform vec4 color;
          uniform float lineWidth;
          uniform float speed;
          
          // 需要返回 czm_material 类型结构体 , 逐顶点绘制
          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            // 定义颜色变量 , 因为 color 为uniform 类型，无法修改
            vec4 outColor = color;
            // 获取默认的一个结构体，在此结构体上进行修改
            czm_material material = czm_getDefaultMaterial(materialInput);

            // materialInput.st UV 坐标（已插值） 范围在【0,1】  st.s 为水平分量  st.t 为垂直分量
            vec2 st = materialInput.st;

            float time = fract(czm_frameNumber * speed / 600.0); // czm_frameNumber 为自增变量,除以60帧,为一次动画的计数器
            float xPosition = time; // 设置 线的位置为 时间的位置

            if(st.t > xPosition - lineWidth/2.0 && st.t < xPosition + lineWidth/2.0) {
              outColor = vec4(0,0,1,1);
            }

            material.diffuse = czm_gammaCorrect(outColor.rgb);  // czm_gammaCorrect 伽马效正，在不同设备上显示相同的效果
            material.alpha = outColor.a; // 透明度
            return material;
          }
        `
        const myMaterial = new Cesium.Material({
          translucent: false,
          fabric: {
            type: 'test',
            uniforms: {
              color: new Cesium.Color(1, 0, 0, 1),
              lineWidth: 0.1, // 线的宽度， 0-1 之间 为占比
              speed: 5, // 速度
            },
            source: shaderSource
          }
        })
        setMeterial(myMaterial) // 设置材质
      }
    },
    {
      text: "自定义材质-动态渐变线(x方向)",
      onselect: function () {
        // 片元着色器
        const shaderSource = `
          // 接受 uniform 传参 为四维向量 color 代表颜色
          uniform vec4 color;
          uniform vec4 heightColor;
          uniform float lineWidth;
          uniform float speed;
          
          // 需要返回 czm_material 类型结构体 , 逐顶点绘制
          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            // 定义颜色变量 , 因为 color 为uniform 类型，无法修改
            vec4 outColor = color;
            // 获取默认的一个结构体，在此结构体上进行修改
            czm_material material = czm_getDefaultMaterial(materialInput);

            // materialInput.st UV 坐标（已插值） 范围在【0,1】  st.s 为水平分量  st.t 为垂直分量
            vec2 st = materialInput.st;

            float time = fract(czm_frameNumber * speed / 600.0); // czm_frameNumber 为自增变量,除以60帧,为一次动画的计数器
            float xPosition = time; // 设置 线的位置为 时间的位置

            outColor.a = 0.0; // 所有区域都是透明
            if(st.s > xPosition - lineWidth/2.0 && st.s < xPosition + lineWidth/2.0) {
              outColor = heightColor;
              outColor.a = (st.s - (xPosition - lineWidth/2.0))/lineWidth;  // 可以理解为 一个线段长度为lineWidth, 每个点到最左侧点所占的百分比即为透明度的值
            }

            material.diffuse = czm_gammaCorrect(outColor.rgb);  // czm_gammaCorrect 伽马效正，在不同设备上显示相同的效果
            material.alpha = outColor.a; // 透明度
            return material;
          }
        `
        const myMaterial = new Cesium.Material({
          translucent: false,
          fabric: {
            type: 'test',
            uniforms: {
              color: new Cesium.Color(1, 0, 0, 1),
              heightColor: new Cesium.Color(0, 0, 1, 1),
              lineWidth: 0.1, // 线的宽度， 0-1 之间 为占比
              speed: 5, // 速度
            },
            source: shaderSource
          }
        })
        setMeterial(myMaterial) // 设置材质
      }
    },
    {
      text: "自定义材质-动态渐变线(y方向)",
      onselect: function () {
        // 片元着色器
        const shaderSource = `
          // 接受 uniform 传参 为四维向量 color 代表颜色
          uniform vec4 color;
          uniform vec4 heightColor;
          uniform float lineWidth;
          uniform float speed;
          
          // 需要返回 czm_material 类型结构体 , 逐顶点绘制
          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            // 定义颜色变量 , 因为 color 为uniform 类型，无法修改
            vec4 outColor = color;
            // 获取默认的一个结构体，在此结构体上进行修改
            czm_material material = czm_getDefaultMaterial(materialInput);

            // materialInput.st UV 坐标（已插值） 范围在【0,1】  st.s 为水平分量  st.t 为垂直分量
            vec2 st = materialInput.st;

            float time = fract(czm_frameNumber * speed / 600.0); // czm_frameNumber 为自增变量,除以60帧,为一次动画的计数器
            float xPosition = time; // 设置 线的位置为 时间的位置

            outColor.a = 0.0; // 所有区域都是透明
            if(st.t > xPosition - lineWidth/2.0 && st.t < xPosition + lineWidth/2.0) {
              outColor = heightColor;
              outColor.a = (st.t - (xPosition - lineWidth/2.0))/lineWidth;  // 可以理解为 一个线段长度为lineWidth, 每个点到最左侧点所占的百分比即为透明度的值
            }

            material.diffuse = czm_gammaCorrect(outColor.rgb);  // czm_gammaCorrect 伽马效正，在不同设备上显示相同的效果
            material.alpha = outColor.a; // 透明度
            return material;
          }
        `
        const myMaterial = new Cesium.Material({
          translucent: false,
          fabric: {
            type: 'test',
            uniforms: {
              color: new Cesium.Color(1, 0, 0, 1),
              heightColor: new Cesium.Color(0, 0, 1, 1),
              lineWidth: 0.1, // 线的宽度， 0-1 之间 为占比
              speed: 5, // 速度
            },
            source: shaderSource
          }
        })
        setMeterial(myMaterial) // 设置材质
      }
    },
    {
      text: "自定义材质-动态渐变线(y方向)-smoothstep 优化版本",
      onselect: function () {
        // 片元着色器
        const shaderSource = `
          // 接受 uniform 传参 为四维向量 color 代表颜色
          uniform vec4 color;
          uniform vec4 heightColor;
          uniform float lineWidth;
          uniform float speed;
          
          // 需要返回 czm_material 类型结构体 , 逐顶点绘制
          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            // 定义颜色变量 , 因为 color 为uniform 类型，无法修改
            vec4 outColor = color;
            // 获取默认的一个结构体，在此结构体上进行修改
            czm_material material = czm_getDefaultMaterial(materialInput);

            // materialInput.st UV 坐标（已插值） 范围在【0,1】  st.s 为水平分量  st.t 为垂直分量
            vec2 st = materialInput.st;

            float time = fract(czm_frameNumber * speed / 600.0); // czm_frameNumber 为自增变量,除以60帧,为一次动画的计数器
            time = pow(time,4.0); // 改变动画函数
            float xPosition = time; // 设置 线的位置为 时间的位置

            // outColor.a = 0.0; // 所有区域都是透明
            // if(st.t > xPosition - lineWidth/2.0 && st.t < xPosition + lineWidth/2.0) {
            //   outColor = heightColor;
            //   outColor.a = (st.t - (xPosition - lineWidth/2.0))/lineWidth;  // 可以理解为 一个线段长度为lineWidth, 每个点到最左侧点所占的百分比即为透明度的值
            // }

            // smoothstep(1.0, 2.0 , num)  num在1.0-2.0之间取差值；  step 函数： 如果  -st.t  小于 -time ；则返回1，否则返回0；
            outColor.a = smoothstep(xPosition - lineWidth, xPosition, st.t)*step(-time ,-st.t);

            material.diffuse = czm_gammaCorrect(outColor.rgb);  // czm_gammaCorrect 伽马效正，在不同设备上显示相同的效果
            material.alpha = outColor.a; // 透明度
            return material;
          }
        `
        const myMaterial = new Cesium.Material({
          translucent: false,
          fabric: {
            type: 'test',
            uniforms: {
              color: new Cesium.Color(1, 0, 0, 1),
              heightColor: new Cesium.Color(0, 0, 1, 1),
              lineWidth: 0.1, // 线的宽度， 0-1 之间 为占比
              speed: 5, // 速度
            },
            source: shaderSource
          }
        })
        setMeterial(myMaterial) // 设置材质
      }
    },
  ];



  function setMeterial(myMaterial) {
    // 普通材质
    const appearance = new Cesium.MaterialAppearance({
      material: myMaterial,
    })

    // 高光材质
    const polylineAppearance = new Cesium.PolylineMaterialAppearance({
      material: myMaterial
    })

    polygonPrimitive.appearance = appearance
    boxPrimitive.appearance = appearance
    polylinePrimitive.appearance = polylineAppearance
    ellipsoidPrimitive.appearance = appearance
  }
});



</script>

<style scoped>
#cesiumContainer {
  width: 100%;
  height: 100%;
}
</style>
